#region Namespace References

using System;
using System.ComponentModel;
using System.Windows.Forms;
using DynConDevCorp.OpenArch.SmartData.Interfaces;
using DynConDevCorp.OpenArch.SmartData.WinForms.ControlBinders;

#endregion

namespace DynConDevCorp.OpenArch.SmartData.WinForms
{
    /// <summary>
    /// 
    /// </summary>
    public partial class SmartFieldControl : UserControl
    {
        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="SmartFieldControl"/> class.
        /// </summary>
        public SmartFieldControl()
        {
            InitializeComponent();
        }

        #endregion

        #region Public Instance Properties

        /// <summary>
        /// Gets or sets the binding manager.
        /// </summary>
        /// <value>The binding manager.</value>
        public BindingManagerComponent BindingManager
        {
            get { return m_BindingManager; }
            set
            {
                if (m_BindingManager != value)
                {
                    m_BindingManager = value;
                    if (m_PostLoad)
                    {
                        UpdateBindings();
                    }
                }
            }
        }

        /// <summary>
        /// Gets or sets the bound entity.
        /// </summary>
        /// <value>The bound entity.</value>
        public ISmartEntity BoundEntity
        {
            get { return m_BoundEntity; }
            set
            {
                if (value == null)
                    return;
                throw new InvalidOperationException("Direct Entity Binding Not Supported!");
                ////if (m_BoundEntity != value)
                ////{
                ////    m_BoundEntity = value;
                ////    UpdateBindings();
                ////}
            }
        }

        /// <summary>
        /// Gets or sets the name of the bound field.
        /// </summary>
        /// <value>The name of the bound field.</value>
        public string BoundFieldName
        {
            get { return m_BoundFieldName; }
            set
            {
                if (m_BoundFieldName != value)
                {
                    m_BoundFieldName = value;
                    if (m_PostLoad)
                    {
                        UpdateBindings();
                    }
                }
            }
        }

        /// <summary>
        /// Gets or sets the bound smart field.
        /// </summary>
        /// <value>The bound smart field.</value>
        public ISmartField BoundSmartField
        {
            get { return m_BoundSmartField; }
            set
            {
                if (m_BoundSmartField != value)
                {
                    m_BoundSmartField = value;
                    if (m_PostLoad)
                    {
                        UpdateBindings();
                    }
                }
            }
        }

        /// <summary>
        /// Gets or sets the type of the contained control.
        /// </summary>
        /// <value>The type of the contained control.</value>
        [
            Category("Smart"),
            Description("Identifes the Actual Contained Control Type"),
            DefaultValue(typeof (TextBox)),
            TypeConverter(typeof (AvailableControlTypes))
        ]
        public Type ContainedControlType
        {
            get { return m_ContainedControlType; }
            set
            {
                if (value == null)
                    throw new ArgumentNullException("ContainedControlType");
                if (m_ContainedControlType != value)
                {
                    if (m_PostLoad)
                    {
                        if (m_ContainedControlType != null)
                            ReleaseContainedControl();
                        m_ContainedControlType = value;
                        if (m_ContainedControlType != null)
                            UpdateContainedControl();
                    }
                    else
                    {
                        m_ContainedControlType = value;
                    }
                }
            }
        }

        /// <summary>
        /// Gets or sets the input update.
        /// </summary>
        /// <value>The input update.</value>
        public InputUpdateMode InputUpdate
        {
            get { return m_InputUpdate; }
            set
            {
                if (m_InputUpdate != value)
                {
                    m_InputUpdate = value;
                    if (m_PostLoad)
                    {
                    }
                }
            }
        }

        /// <summary>
        /// Gets or sets the text align.
        /// </summary>
        /// <value>The text align.</value>
        public HorizontalAlignment TextAlign
        {
            get { return m_TextAlign; }
            set
            {
                if (m_TextAlign != value)
                {
                    m_TextAlign = value;
                    if (m_PostLoad)
                    {
                    }
                }
            }
        }

        #endregion

        #region Protected Instance Methods

        protected virtual void UpdateBindings()
        {
            if ((m_BindingManager != null) && !String.IsNullOrEmpty(m_BoundFieldName))
            {
                m_BindingManager.BoundEntityChanged += m_BindingManager_BoundEntityChanged;
                UpdateEntityBinding();
            }
            else if ((m_BoundEntity != null) && !String.IsNullOrEmpty(m_BoundFieldName))
            {
            }
            else if (m_BoundSmartField != null)
            {
            }
            else
            {
            }
        }


        /// <summary>
        /// Updates the entity binding.
        /// </summary>
        protected virtual void UpdateEntityBinding()
        {
            if (m_BindingManager != null)
            {
                ISmartEntity entity = m_BindingManager.BoundEntity;
                if (entity != null)
                {
                    m_BoundSmartField = entity[m_BoundFieldName];
                    if (m_BoundSmartField == null)
                        throw new InvalidOperationException("Attempt to Buind Null Field!");
                    if (m_ControlBinder == null)
                        throw new InvalidOperationException("No Control Binder Exists!");
                    m_ControlBinder.BoundSmartField = m_BoundSmartField;
                }
            }
        }

        #endregion

        #region Private Instance Methods

        private void m_BindingManager_BoundEntityChanged(object sender, EventArgs e)
        {
            if (m_ControlBinder != null)
                UpdateEntityBinding();
        }

        private void ReleaseContainedControl()
        {
            Controls.Remove(m_ContainedControl);
            m_ControlBinder.Dispose();
            m_ControlBinder = null;
        }

        private void SmartControl_Load(object sender, EventArgs e)
        {
            UpdateContainedControl();
            m_PostLoad = true;
        }


        private void UpdateContainedControl()
        {
            if (m_BindingManager != null)
            {
                m_BindingManager.BoundEntityChanged += m_BindingManager_BoundEntityChanged;
            }

            m_ContainedControl = (Control) Activator.CreateInstance(m_ContainedControlType);
            Height = Math.Max(Height, m_ContainedControl.GetPreferredSize(Size).Height);
            m_ContainedControl.Height = Height;
            m_ContainedControl.Width = Width;
            m_ContainedControl.Dock = DockStyle.Fill;
            Controls.Add(m_ContainedControl);
            m_ControlBinder = ControlBinderFactory.Global.Create(m_ContainedControl);
            m_ControlBinder.ContainingControl = this;
            m_ControlBinder.TextAlign = TextAlign;
            UpdateEntityBinding();
        }

        #endregion

        #region Fields and Constants

        private BindingManagerComponent m_BindingManager;
        private ISmartEntity m_BoundEntity;
        private string m_BoundFieldName;
        private ISmartField m_BoundSmartField;

        private Control m_ContainedControl;

        private Type m_ContainedControlType = typeof (TextBox);

        /// <summary>
        /// 
        /// </summary>
        protected SmartControlBinder m_ControlBinder;
        private InputUpdateMode m_InputUpdate;

        private bool m_PostLoad;
        private HorizontalAlignment m_TextAlign;

        #endregion
    }

    /// <summary>
    /// 
    /// </summary>
    public class AvailableControlTypes : TypeListConverter
    {
        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="AvailableControlTypes"/> class.
        /// </summary>
        public AvailableControlTypes() : base(ControlBinderFactory.Global.BindableControlTypes)
        {
        }

        #endregion
    }

    /// <summary>
    /// 
    /// </summary>
    public enum InputUpdateMode
    {
        /// <summary>
        /// 
        /// </summary>
        NoInput,
        /// <summary>
        /// 
        /// </summary>
        CharacterEntryMode,
        /// <summary>
        /// 
        /// </summary>
        LeaveFieldMode
    }
}